https://labuladong.online/algo/data-structure-basic/tree-map-basic/
今天是學習的第 27 天,主要學習了 TreeMap / TreeSet 實現原理:
TreeMap
和哈希表 HashMap
的資料結構類似,都是儲存鍵值對 key-value
,差別在於:
特性 | HashMap | TreeMap |
---|---|---|
底層結構 | 陣列 | 二叉搜索樹 |
有序性 | 無序 | 有序 |
時間複雜度 | O(1) | O(log n) |
適用場景 | 快速查找 | 需要處理鍵的大小關係 |
這是一個基本的 TreeNode
結構:
var TreeNode = function(val) {
this.val = val;
this.left = null;
this.right = null;
};
只需要調整這個 TreeNode
結構,就可以用來實現 TreeMap
:
class TreeNode {
constructor(key, value) {
this.key = key;
this.value = value;
this.left = null;
this.right = null;
}
}
這是一個 TreeMap
的結構,雖然哈希表 HashMap
很實用,但是它沒有辦法很好的處理鍵之間的大小關係。
// TreeMap 主要接口
class MyTreeMap<K, V> {
// ****** Map 鍵值映射的基本方法 ******
// 增/改,複雜度 O(log n)
public void put(K key, V value) {}
// 查,複雜度 O(log n)
public V get(K key) {}
// 刪,複雜度 O(log n)
public void remove(K key) {}
// 是否包含鍵 key,複雜度 O(log n)
public boolean containsKey(K key) {}
// 返回所有鍵的集合,結果有序,複雜度 O(log n)
public List<K> keys() {}
// 查找小於等於 key 的最大鍵,複雜度 O(log n)
public K floorKey(K key) {}
// 查找大於等於 key 的最小鍵,複雜度 O(log n)
public K ceilingKey(K key) {}
// 查找排名為 k 的鍵,複雜度 O(log n)
public K selectKey(int k) {}
// 查找鍵 key 的排名,複雜度 O(log n)
public int rank(K key) {}
// 區間查找,複雜度 O(log n + m),m 為區間大小
public List<K> rangeKeys(K low, K high) {}
}
核心原則:二叉搜索樹的性能取決於樹的高度,樹的高度取決於樹的平衡性
平衡樹 vs 不平衡樹
狀態 | 樹高 | 時間複雜度 | 視覺特徵 |
---|---|---|---|
平衡 | O(log n) | O(log n) | 左右子樹高度相近 |
不平衡 | O(n) | O(n) | 退化成單鏈表 |
這是一棵平衡的二叉搜索樹:
這是一棵不平衡的二叉搜索樹,所有節點都只有右子樹,沒有左子樹:
TreeMap
的底層資料結構是二叉搜索樹